#pragma once

#include <QPixmap>
#include <QStack>
#include <QStylePainter>
#include <QVector>
#include <QWidget>

struct CmdWindowInfo {
  QString title;
  QString url;
  QString params;  // same command, different parameters
  int cmdId = 0;
  int winId = -1;
  char flag = 0;  //{1:web, 2:fixed, 4:hide, 8:seperated}
  QRect rect;
  QWidget* widget = nullptr;

  void setWebFlag() { flag = flag | 0x01; }
  bool isWeb() const { return (flag & 0x01) == 0x01; }
  void setFixed(bool v) {
    if (v)
      flag = flag | 0x02;
    else
      flag = flag & 0xFD;
  }
  bool isFixed() const { return (flag & 0x02) == 0x02; }

  bool isHide() const { return (flag & 0x04) == 0x04; }
  void setHide(bool v) {
    if (v)
      flag = flag | 0x04;
    else
      flag = flag & 0xFB;
  }

  bool isPopup() const { return (flag & 0x08) == 0x08; }
  void setPopup(bool v) {
    if (v)
      flag = flag | 0x08;
    else
      flag = flag & (~0x08);
  }
};

struct LayoutInfo {
  bool fixedWidth = false;
  int max_tab_width = 90;
  int min_tab_width = 55;
  int image_top_gap = 7;
  int image_gag = 5;  // 图片两侧空白
  int tab_image_height = 29 /*31*/;
  int tab_overlap = 0 /*4*/;  // 标签叠加
  int active_tab_width = max_tab_width;
  int normal_tab_width = max_tab_width;
  int group_gap = 0 /*10*/;  // 固定标签组间隔
  int right_btn_width = 24;
  int max_fixed_tab_count = 5;
  int close_btn_width = 12;
  int clost_btn_gap = 5;
  bool showMore = false;

  void applyScale(float scale) {
    max_tab_width = 90 * scale;
    min_tab_width = 55 * scale;
    image_top_gap = 7 * scale;
    tab_image_height = 29 /*31*/ * scale;
    tab_overlap = 0 /*4*/ * scale;
    active_tab_width = max_tab_width;
    group_gap = 0 /*10*/ * scale;
    right_btn_width = 24 * scale;
    close_btn_width = 12 * scale;
    clost_btn_gap = 5 * scale;
  }
};

class SImageButton;
class QPropertyAnimation;
class QAction;

class TabBar : public QWidget {
  Q_OBJECT
  Q_PROPERTY(int animateProgess READ progress WRITE setProgress)
 public:
  TabBar(QWidget* parent);

  CmdWindowInfo& addTab(const QString& title, QWidget* ctrl = nullptr,
                        int cmdId = 0, bool fixed = false);
  CmdWindowInfo* tabById(int tabId);
  int tabForCmd(int id, const QString& params);
  void activateTabByTabId(int tabId);
  void updateTabTitle(int tabId, const QString& title);
  void attachWidget(CmdWindowInfo cwi);
  int leftSpace() const;
  bool tabShrinked() const {
    return m_layout.normal_tab_width < m_layout.max_tab_width;
  }

 protected:
  bool event(QEvent* event) override;
  void mousePressEvent(QMouseEvent* event) override;
  void mouseDoubleClickEvent(QMouseEvent* event) override;
  void mouseReleaseEvent(QMouseEvent* event) override;
  void mouseMoveEvent(QMouseEvent* event) override;
  void paintEvent(QPaintEvent* event) override;
  void resizeEvent(QResizeEvent* event) override;
  void leaveEvent(QEvent* event) override;
  void dragEnterEvent(QDragEnterEvent* event) override;
  void dragLeaveEvent(QDragLeaveEvent* event) override;
  void dragMoveEvent(QDragMoveEvent* event) override;
  void dropEvent(QDropEvent* event) override;
  void contextMenuEvent(QContextMenuEvent* event) override;

 signals:
  void tabActivated(int newTabId);
  void tabClose(int tabId);
  void tabSeperated(CmdWindowInfo ti);
  void requestResize(int type);

 protected slots:
  void onBtnClicked();
  void onAction();

 private:
  void layoutTabs(bool reset = false);
  void drawTab(QStylePainter& painter, const CmdWindowInfo& ti,
               bool isActive = false, bool isHoverClose = false);
  void drawMoveBtns(QStylePainter& painter);

  void closeTab(int pos);
  void insertTab(const CmdWindowInfo& ti, int pos);
  void activateWindow(int pos);
  int hitTestTab(QPoint pos);
  int tabPosById(int id);

  void startDrag();
  void doDragMove(int tabPosX);

  void onMoveBtnClicked(bool left);
  bool checkLeftHide() const;
  bool checkRightHide() const;

  QPixmap getDragPixmap() const;

  // animate
  int progress() const { return m_animateProgess; }
  void setProgress(int v);
  void stopAnimation();
  void startAnimation();

  void buildActions();
  void showMoreMenu();
  void unFixTab(int tabPos);

 private:
  LayoutInfo m_layout;
  QVector<CmdWindowInfo> m_tabs;
  int m_activePos = 0;
  int m_fixedCount = 0;
  int m_hoverPos = -1;

  SImageButton* m_btnMore = nullptr;
  SImageButton* m_btnRefresh = nullptr;
  QVector<int> m_hideTabs;
  QRect m_rectMoveLeft;
  QRect m_rectMoveRight;

  bool m_dragging = false;
  QPoint m_startDragPos;
  QPoint m_dragOffset;
  CmdWindowInfo m_dragTab;

  QStack<int> m_activeHistory;  // store the tab id
  bool m_animating = false;
  QVector<CmdWindowInfo> m_tabsForAnimate;
  int m_animateProgess = 0;
  QPropertyAnimation* m_animation = nullptr;

  int m_tabMenu = -1;
  QAction* m_actionRefresh = nullptr;
  QAction* m_actionFix = nullptr;
  QAction* m_actionClose = nullptr;
  QAction* m_actionCloseOthers = nullptr;
  QAction* m_actionCloseAll = nullptr;
  QAction* m_actionCloseAllBonds = nullptr;
  QAction* m_actionUnfixAll = nullptr;
  QAction* m_actionFixedTabWidth = nullptr;
  QAction* m_actionVariantTabWidth = nullptr;

  QPixmap m_pmDragCursor;
};